﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WordNet.Core;
using WordNet.Core.DataContract;
using WordNet.Core.ElementContracts;
using WordNet.Core.Extensions;

namespace Parsers
{
    public class SenseKeyParser: IParser<ISenseKey>
    {
        public static readonly IParser<ISenseKey> Instance = new SenseKeyParser();
        private SenseKeyParser() { }

        public ISenseKey Parse(string key)
        {
            int end = 0;
            Builder builder = new Builder();

            // get lemma
            end = key.IndexOf('%');
            builder.AddLemm(key.Substring(0, end));

            // get ss_type
            int begin = end + 1;
            end = key.IndexOf(':', begin);
            builder.AddSynsetType(key.Substring(begin, end - begin));

            // get lex file
            begin = end + 1;
            end = key.IndexOf(':', begin);
            builder.AddLexFile(key.Substring(begin, end - begin));

            // get lex_id
            begin = end + 1;
            end = key.IndexOf(':', begin);
            int lex_id = int.Parse(key.Substring(begin, end - begin));
            builder.AddLexId(lex_id);

            if (builder.IsAdjectiveSatelatie)
            {
                // get head_word
                begin = end + 1;
                end = key.IndexOf(':', begin);
                builder.AddHead(key.Substring(begin, end - begin));

                // get head_id
                begin = end + 1;
                builder.AddHeadId(key.Substring(begin));
            }

            return builder.Build(key);
        }

        private class Builder
        {
            string lemma;
            int ss_type;
            int lexId;
            POS pos;
            bool isAdjSat;
            ILexFile lexFile;
            string headWord;
            int headId;
            // string key;

            public bool IsAdjectiveSatelatie { get { return isAdjSat; } }

            public Builder AddLemm(string lem)
            {
                this.lemma = lem;
                return this;
            }

            public Builder AddSynsetType(string ssType)
            {
                ss_type = int.Parse(ssType);
                pos = POS.GetPartOfSpeech((DbPartOfSpeechType) ss_type);
                isAdjSat = ss_type.IsAdjectiveSatellite();
                return this;
            }

            public Builder AddLexFile(string file)
            {
                int lexFileNum = int.Parse(file);
                lexFile = LexFile.GetLexicalFile(lexFileNum);
                if (lexFile == null)
                    lexFile = UnknownLexFile.GetUnknownLexicalFile(lexFileNum);
                return this;
            }

            public Builder AddLexId(int lexId)
            {
                this.lexId = lexId;
                return this;
            }

            public Builder AddHead(string head)
            {
                this.headWord = head;
                return this;
            }

            public Builder AddHeadId(string headId)
            {
                this.headId = int.Parse(headId);
                return this;
            }

            public ISenseKey Build(string key)
            {
                if (!IsAdjectiveSatelatie)
                    return new SenseKey(lemma, lexId, pos, lexFile, null, -1, key);
                return new SenseKey(lemma, lexId, pos, lexFile, headWord, headId, key);
            }
        }
    }
}
